function states_ = gXmodality_statelist(varargin)

% get standard and different dot directions from arguments
if ~nargin
    error(sprintf('%s needs arguments', mfilename));
else
    rootArgs = varargin{1};
    std = rootArgs.standard;
    dif = rootArgs.different;

    % quest or no quest?
    if isnan(rootArgs.coherence)

        % use Quest to pick coherences
        VU = @rVarUpdate;
        ptrs = {'dXquest'};

    else

        % let Quest run in the background, fix coherence
        VU = {};
        ptrs = {};
    end

    % modality-specific response mappings
    respond = varargin{2};
    left = varargin{3};
    right = varargin{4};
end

% dots interval viewing time
show = 500;

% space between intervals
sep = 200;

% wait for response time
post = 5000;

% confirm-or-modify-response time
hang = 50;

% acquire central fixation, rebound on touch
acquire = { ...
    'dXkbHID',  {'any', 'error'}; ...
    'dXPMDHID', {'any', 'error'}; ...
    'dXasl',    {[1,true,inf], 'hold', true}};

% hold central or rebound to acquire
hold = { ...
    'dXkbHID',  {'any', 'error'}; ...
    'dXPMDHID', {'any', 'error'}; ...
    'dXasl',    {[1,false,inf], 'acquire', true}};

% settle on tighter fixation or rebound to acquire
settle = { ...
    'dXkbHID',  {'any', 'error'}; ...
    'dXPMDHID', {'any', 'error'}; ...
    'dXasl',    {[2,false,inf], 'acquire', true}};

% maintain central fixation
fixate = { ...
    'dXkbHID',  {'any', 'error'}; ...
    'dXPMDHID', {'any', 'error'}; ...
    'dXasl',    {[2,false,inf], 'error', true}};

% correct response depends on 2afc condition
%   left lever is correct when dXtc = 0 = "same"
%   right lever is correct when dXtc = 1,2 = "different"
lcon = {'jump', {'dXtc', 1, 'value'}, [0 1 2], {'correct'; 'incorrect'; 'incorrect'}};
rcon = {'jump', {'dXtc', 1, 'value'}, [0 1 2], {'incorrect'; 'correct'; 'correct'}};

% state function and argument shorthand
GS = @rGraphicsShow;
fp = {'dXtarget', 1};
tx = {'dXtext', 1:2};
dt = {'dXdots', 1};
tg = {tx{:},{},dt{:},fp{:}};

CT = @centerTargetOnFixation;
ctf = {2, 200};%, 'diameter2', 2};%, 'visible', true};

SP = @rPlay;
bp = 'dXbeep';
sd = 'dXsound';

% check the dXtc to get 2afc condition and set dXdots direction
P2 = @pick2afcStim;

%   name        fun args        jump    wait    repsDrawQuery   cond
arg_dXstate = {{ ...
    'clear',    {}, {},         'next', 0,      0,  5,  0,      {}; ...
    'questUp',  VU, ptrs,       'next', 0,      0,  0,  0,      {}; ...
    ...
    'indicate', GS, fp,         'next', 0,      0,  3,  0,      {}; ...
    'acquire',  {}, {},         'error',3e4,    0,  0   acquire,{}; ...
    'hold',     {}, {},         'next', 350,    0,  0,  hold,   {}; ...
    'recenter', CT, ctf,        'next', 0,      0,  0,  1,      {}; ...
    'settle',   {}, {},         'next', 150,    0,  0,  settle, {}; ...
    ...
    'pickInt1',	P2, {1,std,dif},'next', 0,      0,  0,  1,      {}; ...
    'onInt1',	GS, dt,         'next', 0,      0,  0,  1,      {}; ...
    'tone1',	SP, {bp,2},     'next', 500,	0,  0,  1,      {}; ...
    'tone2',	SP, {bp,3},     'next', 500,	0,  0,  1,      {}; ...
    ...
    'showInt1', {}, {},         'next', show,   0,  1,  fixate,	{}; ...
    'offInt1',  GS, {{},dt{:}}  'next', sep/3,  0,  3,  1,      {}; ...
    'pickInt2', P2, {2,std,dif},'next', sep/3,  0,  0,  1,      {}; ...
    'onInt2',	GS, dt,         'next', sep/3,  0,  0,  1,      {}; ...
    'showInt2', {}, {},         'next', show,   0,  1,  1,      {}; ...
    ...
    'respond',  GS, tg,         'error',post,   0,  3,  respond,{}; ...
    'left',     {}, {},         'error',hang,	0,  0,  left,   lcon; ...
    'right',    {}, {},         'error',hang,	0,  0,  right,  rcon; ...
    'both',     {}, {},         'error',0,      0,  0,  0,      {}; ...
    ...
    'correct',  SP, {sd,1},     'end',  500,	0,  0,  0,      {}; ...
    'incorrect',SP, {bp,1},     'end',  500,	0,  0,  0,      {}; ...
    'error',    SP, {bp,1},     'end',  500,	3,  5,  0,      {}; ...
    'end',      {}, {},         'x',    0,      0,  5,  0,      {}; ...
    }};
sz = size(arg_dXstate{1}, 1);

tony = {'current', true, true, false};
states_ = {'dXstate', sz, tony, arg_dXstate};